﻿/*************************************************************************************
 * 工    具：  HK_FirstPersonCam
 * 
 * 描    述：  HK_FirstPersonCam 是一套第一人称相机管理系统，主要功能如下:
 * 
 *            PC端的第一人称相机控制工具；
 *            支持通过鼠标、键盘进行第一人称角色控制；
 *             
 * 使    用：  1.在本项目的 Architecture 中注册 IHK_FirstPersonCamSystem;
 *            2.将场景中需碰撞的物体（如地面等），设置好碰撞体，并设置好Layer；
 *            3.将 FirstPersonPlayer 预设体，拖入场景中；
 *            4.在 FirstPersonPlayer 预设体的 HK_FirstPersonCtrl 组件中，设置好 GroundMask 层级；
 *            5.设置完成后即可通过鼠标、键盘进行操控，按住鼠标右键控制角色旋转，按WASD键控制角色移动；
 *            6.在表现层脚本中通过发送 CMD_ChangeFirstPersonPos 指令（并传入对应参数），可根据目标切换位置；
 *            7.参考 Test_FirstPlayerCamChangePos 进行位置切换设置；
 * 
 * 依    赖：  Dotween
 * 
 * 版    本：  V1.2
 * 作    者：  京产肠饭
 * 
 * 创    建：  2023/06/27  V1.0
 * 
 *            2024/10/23  V1.1
 *            1.功能优化：通过 ActionKit.ScreenTransition 实现眨眼效果，移除Mask物体，减少不同渲染管线的适配工作
 *
 *            2025/05/19  V1.2
 *            1.功能优化：移除对 EventSystem 组件的依赖，优化代码结构
 *            2.代码优化：优化了代码结构，使代码更易读、易维护
 *            3.功能优化：新增了设置鼠标左右键控制相机的选项
 *            4.代码优化：优化对外的接口（指令及事件）
 *            5.功能新增：新增了角色触发器及其对应Event事件
 * 
 * 链    接：  https://gitee.com/JingChanChangFan/hk_-unity-tools
*************************************************************************************/

using System.Collections.Generic;
using QFramework;
using UnityEngine;

namespace HKTools
{
    public interface IHK_FirstPersonCamSystem : ISystem
    {
        HK_FirstPersonCtrl FirstPerson { get; set; }
        void InitFirstPersonCam(HK_FirstPersonCtrl firstPerson);

        void InitCamPosList(HK_FirstPersonPos pos);
        void RemoveFromCamPosList(HK_FirstPersonPos pos);

        void InitCamTriggerList(HK_FirstPersonTrigger trigger);
        void RemoveFromCamTriggerList(HK_FirstPersonTrigger trigger);

        void ChangeFirstPersonPos(HK_FirstPersonPosEnum pos_TF, bool isChangeRot);
        HK_FirstPersonPosEnum CurPos { get; set; }

        void ChangeFirstPersonTrigger(HK_FirstPersonTrigger trigger);
        HK_FirstPersonTrigger CurTrigger { get; set; }
    }

    public class HK_FirstPersonCamSystem : AbstractSystem, IHK_FirstPersonCamSystem
    {
        public HK_FirstPersonCtrl FirstPerson { get; set; }

        public HK_FirstPersonPosEnum CurPos { get; set; }
        // Pos 列表
        List<HK_FirstPersonPos> Pos_List { get; set; }

        public HK_FirstPersonTrigger CurTrigger { get; set; }
        // Trigger 列表
        List<HK_FirstPersonTrigger> Trigger_List { get; set; }

        protected override void OnInit()
        {
            HKDebug.Log("IHK_FirstPersonCamSystem 初始化完成!", LogColor.Cyan, LogStyle.Bold);

            Pos_List = new List<HK_FirstPersonPos>();
            Trigger_List = new List<HK_FirstPersonTrigger>();
        }

        public void InitFirstPersonCam(HK_FirstPersonCtrl firstPerson)
        {
            this.FirstPerson = firstPerson;
        }

        /// <summary>
        /// 初始化 CamPos 列表
        /// </summary>
        public void InitCamPosList(HK_FirstPersonPos pos)
        {
            if (!Pos_List.Contains(pos))
            {
                Pos_List.Add(pos);
            }
        }

        /// <summary>
        /// 从 CamPos 列表 移除
        /// </summary>
        public void RemoveFromCamPosList(HK_FirstPersonPos pos)
        {
            if (Pos_List.Contains(pos))
            {
                Pos_List.Remove(pos);
            }
        }

        public void InitCamTriggerList(HK_FirstPersonTrigger trigger)
        {
            if (!Trigger_List.Contains(trigger))
            {
                Trigger_List.Add(trigger);
            }
        }

        public void RemoveFromCamTriggerList(HK_FirstPersonTrigger trigger)
        {
            if (Trigger_List.Contains(trigger))
            {
                Trigger_List.Remove(trigger);
            }
        }

        public void ChangeFirstPersonPos(HK_FirstPersonPosEnum posType, bool isChangeRot)
        {
            if (FirstPerson == null)
            {
                HKDebug.LogError("FirstPerson未完成初始化！");
                return;
            }

            if (CurPos == posType)
            {
                HKDebug.Log("当前已处于 " + posType.ToString() + " 的位置...");
            }
            else
            {
                HK_FirstPersonPos pos = Pos_List.Find(p => p.posType == posType);

                FirstPerson.GetComponent<CharacterController>().enabled = false;

                ActionKit.ScreenTransition
                  .FadeInOut()
                  .In(fadeIn => fadeIn.Duration(0.4f))
                  .OnInFinish(() =>
                  {
                      FirstPerson.transform.position = pos.transform.position;
                      CurPos = posType;
                      if (isChangeRot)
                      {
                          FirstPerson.ChangeRot(pos.transform);
                      }
                      else
                      {
                          FirstPerson.ResetRot();
                      }
                      FirstPerson.GetComponent<CharacterController>().enabled = true;

                      this.SendEvent(new Event_FPS_ChangePos()
                      {
                          _posType = posType
                      });
                  })
                  .Out(fadeOut => fadeOut.Duration(0.4f))
                  .StartGlobal();
            }
        }

        public void ChangeFirstPersonTrigger(HK_FirstPersonTrigger triggerType)
        {
            if (FirstPerson == null)
            {
                HKDebug.LogError("FirstPerson未完成初始化！");
                return;
            }

            if (triggerType.isOnceTrigger)
            {
                triggerType.Hide();
            }

            this.SendEvent(new Event_FPS_Trigger() { _triggerType = triggerType.triggerType });
        }
    }
}